#include <iostream>
#include "SMsg.h"

using std::cout;
using std::endl;

SMsg::SMsg() {}

SMsg::~SMsg() {}

int SMsg::escape(const char * s, int len, string & out) {
		out.clear();
		if (NULL == s || len < 1) return -1;
		for (int i = 0; i < len; i++) {
				char c = s[i];
				if (SMSG_ESC_CHAR == c || SMSG_SEP_CHAR == c || SMSG_CONN_CHAR == c || SMSG_CARR_RET_CHAR == c || \
								SMSG_LINE_FEED_CHAR == c) out += SMSG_ESC_CHAR;
				out.append(&c, 1);
		}
		return 1;
}

int SMsg::pack(string & str) {
		str.clear();
		string t;
		for (map<string, string>::const_iterator iter = _contents.begin(); _contents.end() != iter; iter++) {
				if (_contents.begin() != iter) str += SMSG_SEP_CHAR;
				escape(iter->first.c_str(), iter->first.size(), t);
				str.append(t.c_str(), t.size());
				str += SMSG_CONN_CHAR;
				escape(iter->second.c_str(), iter->second.size(), t);
				str.append(t.c_str(), t.size()); 
		}
		return 1;
}

int SMsg::unpack(const char * buf, int len) {
		bool is_in_key(true);
		string key, value;
		_contents.clear();
		for (int i = 0; i < len; i++) {
				char c = buf[i];
				if (SMSG_ESC_CHAR == c) {
						if (len - 1 == i) return -1;
						char c1 = buf[i+1];
						if (SMSG_ESC_CHAR != c1 && SMSG_SEP_CHAR != c1 && SMSG_CONN_CHAR != c1 && \
										SMSG_CARR_RET_CHAR != c1 && SMSG_LINE_FEED_CHAR != c1) return -2;
						if (is_in_key)	key.append(&c1, 1);
						else			value.append(&c1, 1);
						i++;
						continue;
				}
				else if (SMSG_CONN_CHAR == c) {
						if (len - 1 == i) return -3;
						is_in_key = false;
						continue;
				}
				else if (SMSG_SEP_CHAR == c) {
						is_in_key = true;
						if (key.size() > 0) {
								_contents.insert(map<string, string>::value_type(key, value));
								key.clear();
								value.clear();
						}
						continue;
				}
				else {
						if (is_in_key)	key.append(&c, 1);
						else			value.append(&c, 1);
						continue;
				}
		}
		if (key.size() > 0) _contents.insert(map<string, string>::value_type(key, value));
		return 1;
}

int SMsg::put(const string & key, const string & value) {
		if (key.size() < 1) return -1;
		_contents.insert(map<string, string>::value_type(key, value));
		return 1;
}

int SMsg::put(const string & key, int value) {
		if (key.size() < 1) return -1;
		char buf[128];
		snprintf(buf, sizeof(buf), "%d", value);
		_contents.insert(map<string, string>::value_type(key, buf));
		return 1;
}

int SMsg::put(const string & key, long long value) {
		if (key.size() < 1) return -1;
		char buf[128];
		snprintf(buf, sizeof(buf), "%lld", value);
		_contents.insert(map<string, string>::value_type(key, buf));
		return 1;
}

int SMsg::get_string_value(const string & key, string & value) {
		if (key.size() < 1) return -1;
		map<string, string>::const_iterator iter = _contents.find(key);
		if (_contents.end() == iter) return -2;
		value = iter->second;
		return 1;
}

int SMsg::get_int_value(const string & key, int & value) {
		if (key.size() < 1) return -1;
		map<string, string>::const_iterator iter = _contents.find(key);
		if (_contents.end() == iter) return -2;
		value = atoi(iter->second.c_str());
		return 1;
}

int SMsg::get_long_long_value(const string & key, long long & value) {
		if (key.size() < 1) return -1;
		map<string, string>::const_iterator iter = _contents.find(key);
		if (_contents.end() == iter) return -2;
		value = atoll(iter->second.c_str());
		return 1;
}
